/*
 * Copyright 1999-2017 Alibaba Group Holding Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package studio.raptor.sqlparser.parser;

import java.util.List;
import studio.raptor.sqlparser.ast.SQLName;
import studio.raptor.sqlparser.ast.statement.SQLColumnDefinition;
import studio.raptor.sqlparser.ast.statement.SQLConstraint;
import studio.raptor.sqlparser.ast.statement.SQLCreateTableStatement;
import studio.raptor.sqlparser.ast.statement.SQLExprTableSource;
import studio.raptor.sqlparser.ast.statement.SQLTableElement;

public class SQLCreateTableParser extends SQLDDLParser {

  public SQLCreateTableParser(String sql) {
    super(sql);
  }

  public SQLCreateTableParser(SQLExprParser exprParser) {
    super(exprParser);
  }

  public SQLCreateTableStatement parseCreateTable() {
    List<String> comments = null;
    if (lexer.isKeepComments() && lexer.hasComment()) {
      comments = lexer.readAndResetComments();
    }

    SQLCreateTableStatement stmt = parseCreateTable(true);
    if (comments != null) {
      stmt.addBeforeComment(comments);
    }

    return stmt;
  }

  public SQLCreateTableStatement parseCreateTable(boolean acceptCreate) {
    if (acceptCreate) {
      accept(Token.CREATE);
    }

    SQLCreateTableStatement createTable = newCreateStatement();

    if (identifierEquals("GLOBAL")) {
      lexer.nextToken();

      if (identifierEquals("TEMPORARY")) {
        lexer.nextToken();
        createTable.setType(SQLCreateTableStatement.Type.GLOBAL_TEMPORARY);
      } else {
        throw new ParserException("syntax error " + lexer.token() + " " + lexer.stringVal());
      }
    } else if (lexer.token() == Token.IDENTIFIER && lexer.stringVal().equalsIgnoreCase("LOCAL")) {
      lexer.nextToken();
      if (lexer.token() == Token.IDENTIFIER && lexer.stringVal().equalsIgnoreCase("TEMPORAY")) {
        lexer.nextToken();
        createTable.setType(SQLCreateTableStatement.Type.LOCAL_TEMPORARY);
      } else {
        throw new ParserException("syntax error");
      }
    }

    accept(Token.TABLE);

    createTable.setName(this.exprParser.name());

    if (lexer.token() == Token.LPAREN) {
      lexer.nextToken();

      for (; ; ) {
        if (lexer.token() == Token.IDENTIFIER //
            || lexer.token() == Token.LITERAL_ALIAS) {
          SQLColumnDefinition column = this.exprParser.parseColumn();
          createTable.getTableElementList().add(column);
        } else if (lexer.token == Token.PRIMARY //
            || lexer.token == Token.UNIQUE //
            || lexer.token == Token.CHECK //
            || lexer.token == Token.CONSTRAINT) {
          SQLConstraint constraint = this.exprParser.parseConstaint();
          constraint.setParent(createTable);
          createTable.getTableElementList().add((SQLTableElement) constraint);
        } else if (lexer.token() == Token.TABLESPACE) {
          throw new ParserException("TODO " + lexer.token());
        } else {
          SQLColumnDefinition column = this.exprParser.parseColumn();
          createTable.getTableElementList().add(column);
        }

        if (lexer.token() == Token.COMMA) {
          lexer.nextToken();

          if (lexer.token() == Token.RPAREN) { // compatible for sql server
            break;
          }
          continue;
        }

        break;
      }

      // while
      // (this.tokenList.current().equals(OracleToken.ConstraintToken)) {
      // parseConstaint(table.getConstraints());
      //
      // if (this.tokenList.current().equals(OracleToken.CommaToken))
      // ;
      // lexer.nextToken();
      // }

      accept(Token.RPAREN);

      if (identifierEquals("INHERITS")) {
        lexer.nextToken();
        accept(Token.LPAREN);
        SQLName inherits = this.exprParser.name();
        createTable.setInherits(new SQLExprTableSource(inherits));
        accept(Token.RPAREN);
      }
    }

    return createTable;
  }

  protected SQLCreateTableStatement newCreateStatement() {
    return new SQLCreateTableStatement(getDbType());
  }

}
